// Copyright 2019 The FlutterCandies author. All rights reserved.
// Use of this source code is governed by an Apache license that can be found
// in the LICENSE file.

import 'dart:async';
import 'dart:io';
import 'dart:typed_data' as typed_data;
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:photo_manager_image_provider/photo_manager_image_provider.dart';

// 添加PlatformUtils导入以支持鸿蒙平台检测
import 'package:photo_manager/platform_utils.dart';

/// 鸿蒙平台专用的AssetEntity图片提供者，解决大图预览加载失败的问题
@immutable
class OhosAssetEntityImageProvider extends ImageProvider<OhosAssetEntityImageProvider> {
  const OhosAssetEntityImageProvider(
    this.entity, {
    this.isOriginal = true,
    this.thumbnailSize = pmDefaultGridThumbnailSize,
    this.thumbnailFormat = ThumbnailFormat.jpeg,
    this.frame = 0,
    this.progressHandler,
  }) : assert(
          isOriginal || thumbnailSize != null,
          "thumbSize must not be null when it's not original",
        );

  /// {@macro photo_manager.AssetEntity}
  final AssetEntity entity;

  /// Choose if original data or thumb data should be loaded.
  /// 选择载入原数据还是缩略图数据。
  final bool isOriginal;

  /// Size for thumb data.
  /// 缩略图的大小。
  final ThumbnailSize? thumbnailSize;

  /// {@macro photo_manager.ThumbnailFormat}
  final ThumbnailFormat thumbnailFormat;

  /// {@macro photo_manager.ThumbnailOption.frame}
  final int frame;

  /// {@macro photo_manager.PMProgressHandler}
  final PMProgressHandler? progressHandler;

  @override
  ImageStreamCompleter loadImage(
    OhosAssetEntityImageProvider key,
    ImageDecoderCallback decode,
  ) {
    return MultiFrameImageStreamCompleter(
      codec: _loadAsync(key, decode),
      scale: 1.0,
      debugLabel: '${key.entity.runtimeType}-'
          '${key.entity.id}-'
          '${isOriginal ? 'origin-' : ''}'
          '${isOriginal ? '' : '$thumbnailFormat'}',
      informationCollector: () {
        return <DiagnosticsNode>[
          DiagnosticsProperty<ImageProvider>('Image provider', this),
          DiagnosticsProperty<OhosAssetEntityImageProvider>('Image key', key),
          DiagnosticsProperty<AssetEntity>('entity', entity),
          DiagnosticsProperty<bool>('isOriginal', isOriginal),
          DiagnosticsProperty<ThumbnailSize>('thumbnailSize', thumbnailSize),
          DiagnosticsProperty<ThumbnailFormat>(
            'thumbnailFormat',
            thumbnailFormat,
          ),
          DiagnosticsProperty<int>('frame', frame),
        ];
      },
    );
  }

  @override
  Future<OhosAssetEntityImageProvider> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<OhosAssetEntityImageProvider>(this);
  }

  Future<ui.Codec> _loadAsync(
    OhosAssetEntityImageProvider key,
    ImageDecoderCallback decode,
  ) {
    // 为鸿蒙平台添加特殊处理，解决线程安全和加载失败问题
    final lock = Completer<ui.Codec>();
    
    Future(() async {
      try {
        assert(key == this);
        if (key.entity.type == AssetType.audio ||
            key.entity.type == AssetType.other) {
          throw UnsupportedError(
            'Image data for the ${key.entity.type} is not supported.',
          );
        }

        typed_data.Uint8List? data;
        if (isOriginal) {
          if (key.entity.type == AssetType.video) {
            data = await key.entity.thumbnailDataWithOption(
              _thumbOption(const ThumbnailSize.square(500)),
              progressHandler: progressHandler,
            );
          } else {
            // 鸿蒙平台特殊处理：优先使用originBytes，添加异常处理和重试机制
            try {
              data = await _loadOriginDataWithRetry(key.entity);
            } catch (e) {
              // 如果获取原图数据失败，尝试使用文件方式
              try {
                final file = await key.entity.loadFile(
                  isOrigin: true,
                  progressHandler: progressHandler,
                );
                data = await file?.readAsBytes();
              } catch (fileError) {
                // 如果文件方式也失败，尝试获取缩略图作为备选方案
                data = await key.entity.thumbnailDataWithOption(
                  _thumbOption(const ThumbnailSize.square(1024)),
                  progressHandler: progressHandler,
                );
              }
            }
          }
        } else {
          // 对于非原始图片，在鸿蒙平台上也使用较大的缩略图以提高清晰度
          final ThumbnailSize effectiveSize = PlatformUtils.isOhos
              ? const ThumbnailSize(800, 800) // 鸿蒙平台使用更大的缩略图
              : thumbnailSize!;
          data = await key.entity.thumbnailDataWithOption(
            _thumbOption(effectiveSize),
            progressHandler: progressHandler,
          );
        }
        
        if (data == null) {
          throw StateError('The data of the entity is null: $entity');
        }
        
        final buffer = await ui.ImmutableBuffer.fromUint8List(data);
        return decode(buffer);
      } catch (e, s) {
        if (kDebugMode) {
          FlutterError.presentError(
            FlutterErrorDetails(
              exception: e,
              stack: s,
              library: 'wechat_assets_picker',
            ),
          );
        }
        // Schedule a microtask to give the cache a chance to add the key.
        Future<void>.microtask(() => _evictCache(key));
        rethrow;
      }
    }).then(lock.complete).catchError(lock.completeError);
    
    return lock.future;
  }

  /// 为鸿蒙平台添加重试机制加载原图数据
  Future<typed_data.Uint8List?> _loadOriginDataWithRetry(AssetEntity entity) async {
    try {
      // 首次尝试
      final data = await entity.originBytes;
      if (data != null && data.isNotEmpty) {
        return data;
      }
    } catch (e) {
      // 首次尝试失败，等待一段时间后重试
      await Future.delayed(const Duration(milliseconds: 100));
    }

    try {
      // 重试一次
      final data = await entity.originBytes;
      if (data != null && data.isNotEmpty) {
        return data;
      }
    } catch (e) {
      // 重试也失败，抛出异常
      rethrow;
    }

    return null;
  }

  ThumbnailOption _thumbOption(ThumbnailSize size) {
    if (Platform.isIOS || Platform.isMacOS) {
      return ThumbnailOption.ios(size: size, format: thumbnailFormat);
    }
    return ThumbnailOption(size: size, format: thumbnailFormat, frame: frame);
  }

  static void _evictCache(OhosAssetEntityImageProvider key) {
    // ignore: unnecessary_cast
    ((PaintingBinding.instance as PaintingBinding).imageCache as ImageCache)
        .evict(key);
  }

  @override
  bool operator ==(Object other) {
    if (other is! OhosAssetEntityImageProvider) {
      return false;
    }
    if (identical(this, other)) {
      return true;
    }
    return entity == other.entity &&
        isOriginal == other.isOriginal &&
        thumbnailSize == other.thumbnailSize &&
        thumbnailFormat == other.thumbnailFormat &&
        frame == other.frame &&
        progressHandler == other.progressHandler;
  }

  @override
  int get hashCode =>
      entity.hashCode ^
      isOriginal.hashCode ^
      thumbnailSize.hashCode ^
      thumbnailFormat.hashCode ^
      frame.hashCode ^
      progressHandler.hashCode;
}

/// 鸿蒙平台专用的AssetEntity图片部件
class OhosAssetEntityImage extends Image {
  OhosAssetEntityImage(
    AssetEntity entity, {
    bool isOriginal = true,
    ThumbnailSize? thumbnailSize = pmDefaultGridThumbnailSize,
    ThumbnailFormat thumbnailFormat = ThumbnailFormat.jpeg,
    int frame = 0,
    PMProgressHandler? progressHandler,
    Key? key,
    ImageFrameBuilder? frameBuilder,
    ImageLoadingBuilder? loadingBuilder,
    ImageErrorWidgetBuilder? errorBuilder,
    String? semanticLabel,
    bool excludeFromSemantics = false,
    double? width,
    double? height,
    Color? color,
    Animation<double>? opacity,
    BlendMode? colorBlendMode,
    BoxFit? fit,
    AlignmentGeometry alignment = Alignment.center,
    ImageRepeat repeat = ImageRepeat.noRepeat,
    Rect? centerSlice,
    bool matchTextDirection = false,
    bool gaplessPlayback = false,
    bool isAntiAlias = false,
    FilterQuality filterQuality = FilterQuality.low,
  }) : super(
          key: key,
          image: OhosAssetEntityImageProvider(
            entity,
            isOriginal: isOriginal,
            thumbnailSize: thumbnailSize,
            thumbnailFormat: thumbnailFormat,
            frame: frame,
            progressHandler: progressHandler,
          ),
          frameBuilder: frameBuilder,
          loadingBuilder: loadingBuilder,
          errorBuilder: errorBuilder,
          semanticLabel: semanticLabel,
          excludeFromSemantics: excludeFromSemantics,
          width: width,
          height: height,
          color: color,
          opacity: opacity,
          colorBlendMode: colorBlendMode,
          fit: fit,
          alignment: alignment,
          repeat: repeat,
          centerSlice: centerSlice,
          matchTextDirection: matchTextDirection,
          gaplessPlayback: gaplessPlayback,
          isAntiAlias: isAntiAlias,
          filterQuality: filterQuality,
        );
}